home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 June: Reference Library / Dev.CD Jun 94.toast / Technical Documentation / Mac Tech Notes (DocViewer) / QuickTime / QT05-Component Mgr 3.0 / QT05-Component Mgr 3.0
Encoding:
Text File  |  1994-04-27  |  90.9 KB  |  233 lines  |  [ONLN/HLX2]

  1. QT 05 - Component Manager version 3.0
  2. QuickTime    & Dave Radcliffe    March 1994
  3. This note contains information regarding the version of the Component Manager that shipped with QuickTime 1.6 and the changes necessary to support native PowerPC components.
  4. Topics
  5. • QuickTime 1.6 and Component Manager 3.0
  6. • Native PowerPC components
  7. Introduction
  8. The Component Manager in QuickTime 1.6.x and for the Power Macintosh (PowerPC) release has some new features. It has added the ability to automatically resolve conflicts between different versions of the same component. It will ensure that only the most recent version of a given component is actually registered. The Component Manager now supports Icon Suites for a component, so a component’s icon no longer has to be just black and white. In addition, the Component Manager can support code written in the native format of the PowerPC.
  9. The result returned for the Gestalt selector gestaltComponentMgr will be 3, indicating version number 3 of the Component Manager. This is the version being discussed in this note. To insure that you have the features discussed here, check that version 3 is installed.
  10. For support of the Power Macintosh, the Component Manager has been extended to allow use of native PowerPC components. When the Component Manager loads a native component on the Power Macintosh, it calls uses the Code Fragment Manager and calls GetMemFragment and then later CloseConnection when it unloads your code resource (specified in a ComponentPlatformInfo). This is how the Component Manager supports a native code fragment.
  11. A component can support multiple platforms such as the 68K and PowerPC. Existing 68K code is always supported on the Power Macintosh through emulation. But you can also have native PowerPC code for your component to support better performance. The Component Manager will allow you to create a component that contains both code formats, so that you can support all platforms with a single component. The Component Manager also was extended in a way that allows for native PowerPC only components (without any 68K code support).
  12. Extended ComponentResource
  13. The ComponentResource data structure (the 'thng' resource) has been extended. These extensions define additional information about the component. The complete data structure is shown below. The first portion is the same as the existing ComponentResource, with the new fields added at the end. The Component Manager determines if it is present by examining the size of the 'thng' resource.
  14. struct ExtComponentResource {
  15.     ComponentDescription    cd;            /* Registration parameters */
  16.     ResourceSpec     component;            /* resource where Component code                                is found */
  17.     ResourceSpec    componentName;        /* name string resource */
  18.     ResourceSpec    componentInfo;        /* info string resource */
  19.     ResourceSpec    componentIcon;        /* icon resource */
  20.     /* new data for Component Manager version 3 */
  21.     long        componentVersion;        /* version of Component */
  22.     long        componentRegisterFlags;    /* flags for registration */
  23.     short        componentIconFamily;        /* resource id of Icon Family */
  24.     long        count;                /* elements in platformArray */
  25.     ComponentPlatformInfo platformArray[1];
  26. };
  27. componentVersion 
  28. The componentVersion field contains the version number of the component. This should be identical to the value returned by GetComponentVersion. For convenience, if this value is set to 0, the component is called to get the version. This is useful during development. The version number stored in the ComponentResourceExtension is used by the Component Manager to avoid having to load and call the component to retrieve the component’s version during startup.
  29. componentRegisterFlags
  30.  
  31. The componentRegisterFlags allow you to define additional register information. These flags are discussed below. 
  32. /* Component Resource Extension flags */
  33. componentDoAutoVersion             = (1<<0)
  34. componentWantsUnregister            = (1<<1)
  35. componentAutoVersionIncludeFlags        = (1<<2)
  36. componentHasMultiplePlatforms        = (1<<3)    
  37. The componentDoAutoVersion flag tells the Component Manager that you want your component registered only if there is no later version available. If there is an older version of the component installed, it will be unregistered. If an older version of the same component attempts to register after you, it will be immediately unregistered. Further, if a newer version of the same component registers after you, you will automatically be unregistered. Using the automatic version control feature of the Component Manager allows you to make sure that only the most recent version of your software is running on a given machine, regardless of how many versions may be installed.
  38. The componentWantsUnregister flag indicates that your component wants to be called when it is unregistered. This is useful if your component allocates global memory at register time, for example. The prototype of the unregister message is identical to the register message. If your component has never been opened, its unregister message is not be called. The routine selector for unregister is given below.
  39. kComponentUnregisterSelect         = -7 
  40. The componentAutoVersionIncludeFlags flag tells the Component Manager to use the component flags as criteria for its component search. If a component wants automatic version control, the Component Manager has to search for similar components. Normally, the Component Manager searches only for another component using the type, subType, and manufacturer fields of a ComponentDescription record. This flag tells the Component Manager to include the componentFlags in its search.
  41. The componentHasMultiplePlatforms flag indicates that your component contains multiple versions of the code for different platforms. If you plan on supporting the PowerPC native code format, then you need to use the ComponentPlatformInfo within the component resource structure. Then set this bit in the componentRegisterFlags field. If this bit is not set then the code is assumed to be 68K format. Without this flag being set, the Component Manager will ignore any ComponentPlatformInfo.
  42. componentIconFamily 
  43. Finally, the componentIconFamily field allows you to provide the resource ID of a System 7 Icon Suite. If this field is 0, it indicates that there is no icon suite.
  44. count
  45. This is the number of elements contained in the ComponentPlatformInfo array.
  46. platformArray
  47. This is an array of elements that describe the code to be used for different platforms. If the platform is for 68K, then the information within this element is a copy from the componentFlags of the ComponentDescription and ResourceSpec of the original ComponentResource structure. This insures backwards compatibility with older Component Managers. If the component contains native code support for the PowerPC, then an element of the array will contain the information about its componentFlags, resource type, and resource ID.
  48. The platformType field is a value that represents which platform the component code is to support. The Gestalt result for selector gestaltSysArchitecture will be matched with the value in platformType of the ComponentResource. If a match is found, then that code is used to support the given platform.
  49.     gestalt68k        = 1,            /* Motorola MC68K architecture */
  50.     gestaltPowerPC    = 2,            /* IBM PowerPC architecture */
  51. struct ComponentPlatformInfo
  52. {
  53.     long            componentFlags;    /* flags of Component */
  54.     ResourceSpec        component;        /* resource where Component code                                is found */
  55.     short            platformType;        /* gestaltSysArchitecture result */
  56. };
  57. Component Manager version 3 routines
  58. GetComponentIconSuite
  59. GetComponentIconSuite returns an Icon Suite for the given component. This call works only under System 7 or later. If called on System 6, it returns an error. If the component doesn’t have an Icon Suite but does have a Component Icon (as returned by GetComponentInfo), GetComponentIconSuite creates an Icon Suite containing just the black-and-white Component Icon. In this way, you can use GetComponentIconSuite whether or not a component has an Icon Suite.
  60. pascal OSErr GetComponentIconSuite(Component aComponent, Handle *iconSuite)
  61. aComponent    Component ID, retrieved with FindNextComponent.
  62. iconSuite    Pointer to the Icon Suite you will receive.
  63. RegisterComponent
  64. RegisterComponentResource
  65. RegisterComponentResourceFile
  66. The only change made to these routines was to modify the use of the global parameter. The upper byte now contains the platform ID to be used by the component being registered. This change is necessary because these calls do not have access to the ComponentResource which contains the ComponentPlatformInfo. If the upper byte of the global parameter is zero, then the platform is assumed to be the platform68k.
  67. How to create a PowerPC ComponentResource
  68. The basics step for running on a Power Macintosh with a native component are:
  69. •  Create component code fragment with native PowerPC code
  70. •  Main entry point to code is a mixed mode routine descriptor
  71. •  Package component code fragment as a resource
  72. •  If you supply an interface for the component to be called directly, then for PowerPC code to    
  73.    call your component you must provide custom glue to make the call.
  74. •  Create the extended 'thng' resource using the ComponentPlatformInfo
  75. Each of these steps are discussed in more detail below:
  76. Creating the component code fragment
  77. The first step in creating a native PowerPC component is to port your code.  For complete details on porting to PowerPC, see Inside Macintosh: PowerPC System Software.  Especially important for the following discussion is an understanding of the Mixed Mode and Code Fragment Managers.
  78. Like other code ported for PowerPC, anytime your code uses a callback function (ProcPtr), it must be converted to a UniversalProcPtr.  But unlike callbacks defined by the system, callbacks to your component have their own function prototypes.  With the exception of some callbacks defined for QuickTime components, there are no system supplied function prototypes or UniversalProcPtrs, so you must create these yourself.
  79. If, in response to a request code, your component dispatches to internal functions using CallComponentFunction or CallComponentFunctionWithStorage, then this is a place where you must use a UniversalProcPtr.
  80. Suppose your component currently responds to an open request as follows:
  81.     switch (params->what)
  82.     {
  83.         case kComponentOpenSelect:    /* Open request */
  84.         {
  85.         result = CallComponentFunctionWithStorage (storage, params, MyOpen);
  86.         break;
  87.         }
  88. MyOpen is an internal function callback, so you must create a RoutineDescriptor/UniversalProcPtr for it.  MyOpen is declared as follows:
  89. pascal ComponentResult MyOpen (Handle storage, ComponentInstance self);
  90. The first step is to create a ProcInfo value for this function:
  91. enum {
  92.    uppMyOpenProcInfo = kPascalStackBased
  93.     | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  94.     | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  95.     | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(ComponentInstance)))
  96. };
  97. Next you must update your source to build a UniversalProcPtr and use it.  You could use NewRoutineDescriptor for this purpose, but the disadvantage is that creates a heap object which your component must dispose of properly.
  98. An alternate approach is to declare a global RoutineDescriptor (global variables are not a problem for a native PowerPC component, since a code fragment automatically has global variables):
  99. #ifdef powerc
  100. RoutineDescriptor MyOpenRD = BUILD_ROUTINE_DESCRIPTOR (uppMyOpenProcInfo, MyOpen);
  101. #endif
  102. If you want your code to be compilable for both 68K and PowerPC, using the Universal Interfaces, then to avoid a lot of conditional compilation, the following macros may be useful:
  103. #ifdef powerc
  104. #define CallComponentFunctionWithStorageUniv(storage, params, funcName) \
  105.    CallComponentFunctionWithStorage(storage, params, &funcName##RD)
  106. #define CallComponentFunctionUniv(params, funcName) \
  107.    CallComponentFunction(params, &funcName##RD)
  108. #define INSTANTIATE_ROUTINE_DESCRIPTOR(funcName) RoutineDescriptor funcName##RD = \
  109.    BUILD_ROUTINE_DESCRIPTOR (upp##funcName##ProcInfo, funcName)
  110. #else
  111. #define CallComponentFunctionWithStorageUniv(storage, params, funcName) \
  112.    CallComponentFunctionWithStorage(storage, params, (ComponentFunctionUPP)funcName)
  113. #define CallComponentFunctionUniv(params, funcName) \
  114.    CallComponentFunction(params, (ComponentFunctionUPP)funcName)
  115. #endif
  116. These macros, exactly analogous to CallComponentFunction and CallComponentFunctionWithStorage, generate the appropriate code when compiled for 68K and PowerPC.  Note that the PowerPC macro expansion depends on the global RoutineDescriptor name being FuncNameRD, i.e. the name of the function with RD appended.  The INSTANTIATE_ROUTINE_DESCRIPTOR macro can be used for that purpose:
  117. #ifdef powerc
  118. INSTANTIATE_ROUTINE_DESCRIPTOR(MyOpen);
  119. #endif
  120. This is identical to the declaration of MyOpenRD earlier, but simplifies the editing.
  121. With all the conditional stuff out of the way, then the original code can simply be updated by replacing CallComponentFunctionWithStorage with CallComponentFunctionWithStorageUniv:
  122.     switch (params->what)
  123.     {
  124.        case kComponentOpenSelect:        /* Open request */
  125.        {
  126.         result = CallComponentFunctionWithStorageUniv(storage, params,MyOpen);
  127.         break;
  128.        }
  129. Repeat the above steps for all internal component dispatches you make.
  130. Setting the main entry point
  131. Lastly, you must set up the entry point into your component correctly.  Unlike a 68K code resource, a PowerPC code fragment (which your component will be) has a well defined entry point.  The Component Manager, rather than just jumping to the start of the code resource, will call the main entry point, as defined when linking, instead.
  132. But the Component Manager is 68K code, which means your main entry point must be a RoutineDescriptor.  You can set that up as follows:
  133. pascal    ComponentResult    main    (ComponentParameters    *params,
  134.                      Handle          storage);
  135. #ifdef powerc
  136. enum {
  137.     uppMainProcInfo = kPascalStackBased 
  138.         | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) 
  139.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentParameters *))) 
  140.         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Handle)))
  141. };
  142. RoutineDescriptor MainRD = BUILD_ROUTINE_DESCRIPTOR(uppMainProcInfo, main);
  143. #endif
  144. When you link the component, you must then specify MainRD as the entry point.
  145. Note:    Your development environment may issue a warning because your main entry point is in a data section, not a code section.  You may ignore the warning.
  146. Note:    If your code is dependent on C or C++ runtime initializations, then your main entry point would be __start or __cplusstart, respectively, rather than main.  Modify the previous example accordingly.
  147. Note: Some components rely on a “fast dispatching” mechanism for calling component functions.  This mechanism is dependent on the 68K architecture and is unsupported for native components, although it will work for emulated components running on the Power Macintosh.
  148. Note: In all these modifications for PowerPC, the most difficult thing to get right is the ProcInfo value.  It’s very easy to make a “cut and paste” error, or get a type wrong (short instead of short *).  If your component is crashing the first thing to check (and check and check and check!) are the ProcInfo values.
  149. Packaging the PowerPC component into a resource
  150. PowerPC development tools create your PowerPC code in a code fragment in the data fork of the file.  Your component code must be a resource (the resource type and id are specified in the 'thng' resource described below).  You can use the MPW Rez “read” command to read from the data fork into a resource.  For example:
  151.     read 'mycp' (130) mycomponent.pef;
  152. reads the code fragment from the file mycomponent.pef and creates the resource 'mycp'(130).
  153. Providing an interface to the component
  154. If you wish your component to be called directly, you must also supply an interface so callers know how to call it.  For standard functions, such as Open, Close, Version, etc., this is not a problem as the Component Manager supplies functions to do this for you.  Nor is this a problem if you are writing QuickTime components, as QuickTime supplies standard interfaces and libraries for calling components.
  155. But one of the advantages of the Component Manager is it lets you define your own routines with their own parameter lists, and for these routines you must supply an interface.  Typically, for 68K this involved providing callers an interface file with function prototypes for your calls and inline 68K assembly to actually make the call.
  156. Obviously, the inline 68K code is a problem for a native PowerPC caller, so you must provide glue to accomplish the same thing.  The following discussion also applies to calling a 68K component from PowerPC code.  The interface is the same, either way.
  157. To take the example for Inside Macintosh: More Macintosh Toolbox, page 6-30, you might have a call like:
  158. pascal ComponentResult DrawerSetup (ComponentInstance myInstance, Rect *r) =
  159.     ComponentCallNow (kDrawerSetUpSelect, 4);
  160. ComponentCallNow is a macro that expands to inline 68K code that pushes additional parameters and then executes an A-trap to call the Component Manager.
  161. The first thing when using the new Universal Headers, is that the definition of ComponentCallNow has changed slightly.  The above declaration would change to:
  162. pascal ComponentResult DrawerSetup (ComponentInstance myInstance, Rect *r) 
  163.     ComponentCallNow (kDrawerSetUpSelect, 4);
  164. The only difference in this declaration is that the ‘=’ character is missing.  This is necessary to allow the code to compile for both 68K and PowerPC.
  165. For 68K code, ComponentCallNow continues to expand to inline 68K code, but for PowerPC, the ComponentCallNow macro expands to nothing, which means the above declaration reduces to:
  166. pascal ComponentResult DrawerSetup (ComponentInstance myInstance, Rect *r) ;
  167. You must now supply glue for DrawerSetup that does the same thing on PowerPC as the 68K inlines would do.  
  168. The strategy here is to mimic what 68K code calling your component would do.  Namely, push a bunch of parameters on the stack, then call the component.  You do that by building a struct that looks like the parameters as they would appear on the 68K stack.  Each call will require a different struct because each call can have different parameters.
  169. Use the struct below (DrawerSetupGluePB) as a template.  The first three fields, componentFlags, componentParamSize, and componentWhat are required, as is the last field, which is the component instance.
  170. componentFlags is unused and should be zero.
  171. componentParamSize is the size, in bytes, of the parameters to the call, not counting the component instance.  This is the same number that is passed as the second parameter in a ComponentCallNow macro call, and should be the same as the size of the params struct, discussed below.
  172. componentWhat is the selector for your component call.  Its the same as the first parameter to a ComponentCallNow macro call.
  173. The params field is a separate struct that exactly mirrors your parameters.   This must be customized for your call.  A separate struct is used here because it simplifies the sizeof calculation for the componentParamSize field.  Parameters in this struct are specified in reverse order from the parameter list.
  174.  
  175. Note:    Remember that the struct mirrors 68K stack alignment, not 68K struct alignment.  This means that byte parameters, e.g. char or Boolean, get passed as two bytes, not one. The struct must mirror that fact, so you must declare byte fields to be a byte field followed by a pad byte field and take it into account in your parameter size calculations.
  176.  
  177. Once you have the struct, initialize it as shown in the example, and call the component via CallUniversalProc with the CallComponentUPP.  CallComponentUPP is declared for you and is part of the InterfaceLib.  You don't need to do anything special to use it.
  178. uppCallComponentProcInfo should have been in the interfaces, because the call is always the same, but it's not, so it's defined below.
  179. enum {
  180.     uppCallComponentProcInfo = kPascalStackBased
  181.         | RESULT_SIZE(kFourByteCode)
  182.         | STACK_ROUTINE_PARAMETER(1, kFourByteCode)
  183. };
  184. Here’s the code for the glue function.  Once you have the structure defined, create an instantiation of it, and initialize it.  Finally, call the component using CallUniversalProc as shown in the example.
  185. pascal  ComponentResult  DrawerSetup (ComponentInstance myInstance, Rect *r) 
  186. {
  187. #define kDrawerSetupParamSize     (sizeof (DrawerSetupParams))
  188. #ifdef powerc
  189. #pragma options align=mac68k
  190. #endif
  191.    struct DrawerSetupParams {
  192.     Rect    *theRect;            /* Your parameters go here!!  In reverse                            order from parameter list. */
  193.    };
  194.    typedef struct DrawerSetupParams DrawerSetupParams;
  195.    struct DrawerSetupGluePB {
  196.     unsigned char        componentFlags;    /* Flags - set to zero */
  197.     unsigned char        componentParamSize;    /* Size of the params struct */
  198.     short            componentWhat;    /* The component request selector */
  199.     DrawerSetupParams    params;        /* The parameters, see above */
  200.     ComponentInstance    instance;        /* This component instance */
  201.    };
  202.    typedef struct DrawerSetupGluePB DrawerSetupGluePB;
  203. #ifdef powerc
  204. #pragma options align=reset
  205. #endif
  206.    DrawerSetupGluePB myDrawerSetupGluePB;
  207.    myDrawerSetupGluePB.componentFlags = 0;
  208.    myDrawerSetupGluePB.componentParamSize = kDrawerSetupParamSize;
  209.    yDrawerSetupGluePB.componentWhat = kDrawerSetUpSelect;
  210.    myDrawerSetupGluePB.params.theRect = r;
  211.    myDrawerSetupGluePB.instance = myInstance;
  212.    return CallUniversalProc(CallComponentUPP,
  213.         uppCallComponentProcInfo,  &myDrawerSetupGluePB);
  214. }
  215. Repeat the above steps for all the public functions for your component.  To allow for future updating, the best way to make this glue available to your clients is to build the glue into a Code Fragment Manager shared library that is built into your component.  Provide your client with an XCOFF file to link against.  That way, if the glue changes, the client applications will not have to be relinked.  Be sure you choose a unique name for the glue library to avoid possible name conflicts.
  216. Creating the extended thng' ComponentResource
  217. Here is how to create the 'thng' ComponentResource for a component that supports both platform68k and platformPowerPC. This is the source for MPW Rez using the latest version of Types.r that supports the UseExtendedThingResource template. Before using the new Types.r you need to define the UseExtendedThingResource conditional with the value 1. A  component defined with this resource will work for all previous versions of the Component Manager. By keeping the original portions of the ComponentResource setup for the platform68k information, it allows your component to work on all 68K Macintosh computers. Adding the new information about your code fragment for the Power Macintosh allows the Component Manager for that machine to use your native code.
  218. resource 'thng' (128, purgeable) {
  219.     kComponentType,
  220.     kComponentSubType,
  221.     kComponentCreator,
  222.     cmpWantsRegisterMessage,
  223.     kAnyComponentFlagsMask,
  224.     k68KCodeType, k68KCodeID,
  225.     'STR ', kComponentNameStringID,
  226.     'STR ', kComponentInfoStringID,
  227.     'ICON', kComponentIconID,
  228. #if UseExtendedThingResource
  229.     0x00010001,                     /* version 1.1 */
  230.     componentHasMultiplePlatforms,
  231.     kComponentIconFamilyID,
  232.     {
  233.         cmpWantsRegisterMessage, k68KCodeType, k68KCodeID, platform68k,
  234.         cmpWantsRegisterMessage, kPowerPCCodeType, kPowerPCCodeID, platformPowerPC
  235.     };
  236. #endif
  237. };
  238. If you have a component that only supports the 68K Macintosh, then you do not need to use the extended ComponentResource structure. However, if you wish to utilize Icon Families and automatic version registration, then use the extended ComponentResource without the ComponentPlatformInfo and do not set the componentHasMultiplePlatforms flag of the componentRegisterFlags. You may also include the ComponentPlatformInfo if you wish to and just have a single element that describes your 68K component code.
  239. If you have a “fat” component, with both 68K and PowerPC code, set the component flags as you would for the 68K only case and duplicate that information in the ComponentPlatformInfo portion of the extended resource.  That will allow your component to work correctly for versions of the Component Manager that are not aware of the extended 'thng' resource.
  240. If you have a component that only supports the PowerPC in native mode, then you must use the extended ComponentResource. In this case, some care must be taken so that the component will not be registered on 68K machines.  Set the ResourceSpec field in the non-extended part of the 'thng' resource to zero. In addition, set the component flags in the non-extended part  of the resource to cmpWantsRegisterMessage, regardless of whether or not you handle the register message.  This will cause the 68K Component Manager to attempt to register your component, it will fail, because there is no 68K code resource and your component will not be registered.
  241. For the PowerPC case, you need to include a single ComponentPlatformInfo element that describes your PowerPC native component code for PowerPC implementations of your component to be registered.  Set the component flags in the extended portion of the resource as you would normally. 
  242. Component Manager interfaces
  243. /* MPW Rez interfaces */
  244. #define cmpWantsRegisterMessage         (1<<31)        /* bits for component 
  245.                                    flags */
  246. #define componentDoAutoVersion         (1<<0)            /* bits for registration
  247.                                       flags */
  248. #define componentWantsUnregister        (1<<1)
  249. #define componentAutoVersionIncludeFlags    (1<<2)
  250. #define componentHasMultiplePlatforms    (1<<3)    
  251.                     
  252. type 'thng' {
  253.     literal longint;                    /* Type */
  254.     literal longint;                    /* Subtype */
  255.     literal longint;                    /* Manufacturer */
  256.     unsigned hex longint;                 /* component flags */
  257.     unsigned hex longint    kAnyComponentFlagsMask = 0;    /* component flags Mask */
  258.     literal longint;                    /* Code Type */
  259.     integer;                        /* Code ID */
  260.     literal longint;                    /* Name Type */
  261.     integer;                        /* Name ID */
  262.     literal longint;                    /* Info Type */
  263.     integer;                        /* Info ID */
  264.     literal longint;                    /* Icon Type */
  265.     integer;                        /* Icon ID */
  266. #if UseExtendedThingResource
  267.     unsigned hex longint;                /* version of Component */
  268.     longint;                        /* flags for registration */
  269.     integer;                        /* resource id of Icon                                    Family */
  270.     longint = $$CountOf(ComponentPlatformInfo);
  271.     wide array ComponentPlatformInfo {
  272.         unsigned hex longint;                 /* component  flags */
  273.         literal longint;                    /* Code Type */
  274.         integer;                        /* Code ID */
  275.         integer platform68k = 1, platformPowerPC = 2;    /* platform type */
  276.         };
  277. #endif
  278. };
  279. /* MPW C interfaces */
  280. enum {
  281. #define gestaltComponentMgr     'cpnt'        /* Component Mgr version */
  282. #define gestaltQuickTimeFeatures     'qtrs'        /* QuickTime features */
  283.     gestaltPPCQuickTimeLibPresent = 0,        /* PowerPC QuickTime glue library                                is present */
  284. #define gestaltSysArchitecture 'sysa'        /* Native System Architecture */
  285.     gestalt68k = 1,                /* Motorola MC68K architecture */
  286.     gestaltPowerPC = 2,                /* IBM PowerPC architecture */
  287.     /* componentRegisterFlags flags for ComponentResourceExtension */
  288.     componentDoAutoVersion         = (1<<0),
  289.     componentWantsUnregister         = (1<<1),
  290.     componentAutoVersionIncludeFlags     = (1<<2),
  291.     componentHasMultiplePlatforms     = (1<<3)
  292. };
  293. struct ComponentPlatformInfo
  294. {
  295.     long            componentFlags;    /* flags of Component */
  296.     ResourceSpec         component;        /* resource where Component code                                is found */
  297.     short            platformType;        /* gestaltSysArchitecture 
  298.                                result */
  299. };
  300. typedef struct ComponentPlatformInfo ComponentPlatformInfo;
  301. struct ExtComponentResource {
  302.     ComponentDescription    cd;            /* Registration parameters */
  303.     ResourceSpec     component;            /* resource where Component code                                is found */
  304.     ResourceSpec    componentName;        /* name string resource */
  305.     ResourceSpec    componentInfo;        /* info string resource */
  306.     ResourceSpec    componentIcon;        /* icon resource */
  307.     /* new data for Component Manager version 3 */
  308.     long        componentVersion;        /* version of Component */
  309.     long        componentRegisterFlags;    /* flags for registration */
  310.     short        componentIconFamily;        /* resource id of Icon Family */
  311.     long        count;                /* elements in platformArray */
  312.     ComponentPlatformInfo platformArray[1];
  313. };
  314. typedef struct ExtComponentResource ExtComponentResource;
  315. Further Reference:
  316. •    Inside Macintosh: More Macintosh Toolbox (Component Manager)
  317. •    Inside Macintosh: PowerPC System Software (Mixed Mode Manager and Code Fragment Manager)
  318. •    Macintosh Technical Note, Drawing Icons the System 7 Way (M.IM.IconDrawing).
  319. “◊#ˇ ˇˇˇˇ#◊†Ç 
  320. 0ZÇ#
  321.     0Ià:µú9"|    ˇˇˇˇˇˇˇˇ#†ƒ°d
  322. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  323. .R…R…+]CNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  324. (|ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ggZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  325. 0(VÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  326.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  327. ([\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  328. IR.°dONLNdq<Ñê(ûZ%QT 05 - Component Manager version 3.0
  329. °dONLNd&É<èp*
  330.     QuickTime°dONLNd0ÉÑè÷)H& Dave Radcliffe°dONLNdAÉ≈è˛(´„
  331. March 1994°dONLNdLù<©T(≈ZThis °dONLNdQùT©˛)Unote contains information regarding the version of the Component Manager that shipped°dONLNdß©<µ›(—ZRwith QuickTime 1.6 and the changes necessary to support native PowerPC components.°dONLNd˙√<œb*Topics°dONLNdœW€2+ )• QuickTime 1.6 and Component Manager 3.0°dONLNd+€WÁ* • Native PowerPC components X
  332. °dONLNdG<!è(=Z Introduction
  333. °dONLNdT/<;o*;The Component Manager in QuickTime 1.6.x and for the Power °dONLNdè/o;˛(WçMacintosh (PowerPC) release°dONLNd´;<G (cZ(has some new features. It has added the °dONLNd”; G˛)œ2ability to automatically resolve conflicts between°dONLNdG<S(oZ-different versions of the same component. It °dONLNd3GS˛)‘2will ensure that only the most recent version of a°dONLNdfS<_∂({ZKgiven component is actually registered. The Component Manager now supports °dONLNd±S∂_˛({‘Icon Suites for°dONLNd¡_<k/(áZ1a component, so a component’s icon no longer has °dONLNdÚ_/k˛)Û,to be just black and white. In addition, the°dONLNdk<w«(ìZOComponent Manager can support code written in the native format of the PowerPC.°dONLNdoá<ìõ*The result returned °dONLNdÉáõì)_for the Gestalt selector ,
  334. Courier°dONLNdúÜíï)ugestaltComponentMgr°dONLNdØáïì˛)Ö will be 3, indicating°dONLNdΔì<üt(ªZ?version number 3 of the Component Manager. This is the version °dONLNdìtü˛(ªíbeing discussed in this note.°dONLNd#ü<´ («ZWTo insure that you have the features discussed here, check that version 3 is installed.°dONLNd{∑<√:*2For support of the Power Macintosh, the Component °dONLNd≠∑:√˛)˛&Manager has been extended to allow use°dONLNd‘√<œô(ÎZof native PowerPC °dONLNdÊ√ôœ˛)]Bcomponents. When the Component Manager loads a native component on°dONLNd)–<‹»(¯Zthe Power Macintosh, it calls °dONLNdG–»‹ú)å)uses the Code Fragment Manager and calls °dONLNdpœú€˛)‘GetMemFragment°dONLNd›<Èá(Zand then later °dONLNdé‹áË)KCloseConnection°dONLNdù›ÈÖ)i when it unloads your code °dONLNd∏›ÖÈ˛)ïresource (specified in a°dONLNd—È<ıœ(ZComponentPlatformInfo°dONLNdÊÍœˆ⁄)ì). °dONLNdÈÍ⁄ˆ˛) 8This is how the Component Manager supports a native code°dONLNd"ˆ<j(Z    fragment.°dONLNd,<º*A component can support °dONLNdDº˛)Ä<multiple platforms such as the 68K and PowerPC. Existing 68K°dONLNdÅ<&U(BZcode °dONLNdÜU&˛)Sis always supported on the Power Macintosh through emulation. But you can also have°dONLNd⁄&<2 (NZ*native PowerPC code for your component to °dONLNd& 2˛)‰)support better performance. The Component°dONLNd.2<>n(ZZ@Manager will allow you to create a component that contains both °dONLNdn2n>˛(Zåcode formats, so that you can°dONLNdå><J(fZ/support all platforms with a single component. °dONLNdª>J˛)fl*The Component Manager also was extended in°dONLNdÊJ<V‚(rZTa way that allows for native PowerPC only components (without any 68K code support). ’X’
  335. *yQT 05 - Component Manager 3.0(Ρ1) of 12(ZM.QT.Component Manager 3.0ˇ°¿Ù%%DSIDICT:_cv
  336. currentdict /bu known {bu}if
  337. userdict /_cv known not{userdict /_cv 30 dict put}if
  338. _cv begin
  339. /bdf{bind def}bind def
  340. currentscreen/cs exch def/ca exch def/cf exch def
  341. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  342. /ss{//cf //ca //cs setscreen}bdf
  343. /stg{ss setgray}bdf
  344. /strgb{ss setrgbcolor}bdf
  345. /stcmyk{ss cvcmyk}bdf
  346. /min1{dup 0 eq{pop 1}if}bdf
  347. end
  348. currentdict /bn known {bn}if
  349. †ø`◊#ˇ ˇˇˇˇ#◊ 
  350. IR, Palatino
  351. .+6-Macintosh Technical Notes 040˘,Times
  352. °dONLNd!‡*Extended ComponentResource
  353. °dONLNd0<˝*+The ComponentResource data structure (the ',
  354. Courier°dONLNdF/˝;)Âthng°dONLNdJ0<U) ' resource) °dONLNdV0U<⁄)<has been extended. These°dONLNdo<Hå(d6Kextensions define additional information about the component. The complete °dONLNd∫<åH⁄(d™data structure is°dONLNdÃIUt(q6shown below. The °dONLNd›ItU4)\*first portion is the same as the existing °dONLNdH4T´)¿ComponentResource°dONLNdI´U⁄)w
  355. , with the°dONLNd#UaÓ(}6+new fields added at the end. The Component °dONLNdNUÓa⁄)÷0Manager determines if it is present by examining°dONLNdbn`(ä6the size of the '°dONLNdêa`m|)Hthng°dONLNdîb|nØ) ' resource.
  356.     °dONLNd†zÖ©(°6struct ExtComponentResource {°dONLNdøÑ<è†+$
  357. ComponentDescription°dONLNd‘Ñ®è∑)lcd;°dONLNd⁄Ñè•)l/* Registration parameters */°dONLNd˘é<ô}(µZ
  358. ResourceSpec °dONLNdéÑô∂)H
  359. component;°dONLNdéôπ)ê!/* resource where Component code °dONLNd<ò£Z*
  360.    is found */°dONLNdL¢<≠x(…Z ResourceSpec°dONLNdY¢Ñ≠ )HcomponentName;°dONLNdi¢≠ñ)ê/* name string resource */°dONLNdÖ¨<∑x(”Z ResourceSpec°dONLNdí¨Ñ∑ )HcomponentInfo;°dONLNd¢¨∑ñ)ê/* info string resource */°dONLNdæ∂<¡x(›Z ResourceSpec°dONLNdÀ∂Ñ¡ )HcomponentIcon;°dONLNd€∂¡s)ê/* icon resource */°dONLNd <’"(ÒZ./* new data for Component Manager version 3 */°dONLNd ‘<flP*
  361. long°dONLNd&‘ÑflŸ)HcomponentVersion;°dONLNd9‘flñ)ê/* version of Component */°dONLNdUfi<ÈP(Zlong°dONLNd[fiÑȘ)HcomponentRegisterFlags;°dONLNdsfiȆ)ê/* flags for registration */°dONLNdëË<ÛU(Zshort°dONLNdòËÑÛË)HcomponentIconFamily;°dONLNdÆËÛ¥)ê /* resource id of Icon Family */°dONLNd–Ú<˝P(Zlong°dONLNd÷ÚÑ˝¢)Hcount;°dONLNd‡Ú˝Ø)ê/* elements in platformArray */°dONLNd¸<ˇ(#Z'ComponentPlatformInfo platformArray[1];°dONLNd)"(-6};
  362. °dONLNd,*Å*componentVersion°dONLNd>7C-*The °dONLNdB6-Bù)componentVersion°dONLNdR7ùC†)p °dONLNdS7†C⁄)?field contains the version number of the component. This should°dONLNdìDP¬(l6&be identical to the value returned by °dONLNdπC¬OG)™GetComponentVersion°dONLNdÃDGP¡)Ö. For convenience, if this °dONLNdÁD¡P⁄)zvalue°dONLNdÌP\î(x6is set to 0, the component °dONLNdPî\⁄)|Dis called to get the version. This is useful during development. The°dONLNdM]i¢(Ö6version number stored in the °dONLNdj\¢hX)äComponentResourceExtension°dONLNdÑ]Xi[)∂ °dONLNdÖ][i⁄)is used by the Component°dONLNdûiu,(ë67Manager to avoid having to load and call the component °dONLNd’i,u⁄(ëJ#to retrieve the component’s version°dONLNd˘uÅ^(ù6during startup.°dONLNd    èõ£*componentRegisterFlags°dONLNd"®¥-*The °dONLNd&ß-≥«)componentRegisterFlags°dONLNd<®«¥)ö) allow you to define additional register °dONLNde®¥⁄)∏information. These°dONLNdx¥¿ï(‹6flags are discussed below.
  363.     °dONLNd‡*(/* Component Resource Extension flags */°dONLNdΩ‚Ìã*componentDoAutoVersion °dONLNd◊‚Ì)ÿ= (1<<0)°dONLNd‡Ï˜ê(6componentWantsUnregister°dONLNd˚Ï˜)ÿ= (1<<1)°dONLNdˆ∏(6 componentAutoVersionIncludeFlags°dONLNd&ˆ)ÿ= (1<<2)°dONLNd/ ©('6componentHasMultiplePlatforms°dONLNdN )ÿ= (1<<3)
  364. °dONLNdX%/(A6The °dONLNd\/$…)componentDoAutoVersion°dONLNdr…%ß)ö+ flag tells the Component Manager that you °dONLNdùß%⁄)fi    want your°dONLNdß%1Ä(M6component registered °dONLNdº%Ä1⁄)hLonly if there is no later version available. If there is an older version of°dONLNd    1=õ(Y6the component installed, it °dONLNd%1õ=⁄)É?will be unregistered. If an older version of the same component°dONLNde=I–(e6aattempts to register after you, it will be immediately unregistered. Further, if a newer version °dONLNdΔ=–I⁄(eÓof°dONLNd…IUT(q6?the same component registers after you, you will automatically °dONLNd    ITU⁄(qrbe unregistered. Using the°dONLNd    #Uaò(}6Nautomatic version control feature of the Component Manager allows you to make °dONLNd    qUòa⁄(}∂sure that only°dONLNd    ÄamÌ(â6,the most recent version of your software is °dONLNd    ¨aÌm⁄)’-running on a given machine, regardless of how°dONLNd    ⁄my∞(ï6many versions may be installed.°dONLNd    ˙Üí-*The °dONLNd    ˛Ö-ë’)componentWantsUnregister°dONLNd
  365. Ü’í⁄)®6 flag indicates that your component wants to be called°dONLNd
  366. Míû~(∫6Kwhen it is unregistered. This is useful if your component allocates global °dONLNd
  367. òí~û⁄(∫úmemory at register°dONLNd
  368. ´û™=(Δ6>time, for example. The prototype of the unregister message is °dONLNd
  369. Èû=™⁄(Δ["identical to the register message. fi4fi˘
  370. (Û62) of 12(ÛqQT 05 - Component Manager 3.0+
  371. M.QT.ComponentManager3.0ˇ ◊#ˇ ˇˇˇˇ#◊ 
  372. IR, Palatino
  373. .+Z-Developer Technical Support(-˙
  374. March 1994 0X0,Times
  375. °dONLNd <,(HZ-If your component has never been opened, its °dONLNd- ,˛)€0unregister message is not be called. The routine°dONLNd^,<8Ô(TZ'selector for unregister is given below.,
  376. Courier
  377.     °dONLNdÜF<Q√*kComponentUnregisterSelect °dONLNd£FQ)¥= -7
  378. °dONLNd©_<kR(áZThe °dONLNd≠^Rj2) componentAutoVersionIncludeFlags°dONLNdÕ_2kc)‡  flag tells °dONLNdŸ_ck˛)1the Component Manager to use°dONLNdˆk<w4(ìZ2the component flags as criteria for its component °dONLNd(k4w˛)¯&search. If a component wants automatic°dONLNdOw<É(üZ'version control, the Component Manager °dONLNdvwɲ)≈3has to search for similar components. Normally, the°dONLNd™Ñ<êÄ(¨Z<Component Manager searches only for another component using °dONLNdÊÑÄê≤(¨û
  379. the type, °dONLNdÉ≤è„)2subType°dONLNd˜Ñ„ê˛)1, and°dONLNd˝ë<ù≥(πZmanufacturer fields of a °dONLNdê≥ú?)wComponentDescription°dONLNd*ë?ù˛)å& record. This flag tells the Component°dONLNdQû<™™(ΔZManager to include the °dONLNdhù™© )ncomponentFlags°dONLNdvû ™K)b in its search.°dONLNdÜ∑<√S(flZThe °dONLNdä∂S¬)componentHasMultiplePlatforms°dONLNdß∑√#)À °dONLNd®∑#√˛)+flag indicates that your component contains°dONLNd‘√<œê(ÎZmultiple versions °dONLNdÊ√êœ˛)TJof the code for different platforms. If you plan on supporting the PowerPC°dONLNd1–<‹z(¯Z native code °dONLNd=–z‹1)>!format, then you need to use the °dONLNd^œ1€ƒ)∑ComponentPlatformInfo°dONLNds–ƒ‹˛)ì  within the°dONLNd›<È(Z0component resource structure. Then set this bit °dONLNdØ›È;)‡in the °dONLNd∂‹;Ë’)componentRegisterFlags°dONLNdÛ’È˛)ö
  380.  field. If°dONLNd◊È<ı_(Z    this bit °dONLNd‡È_ı˛)#Vis not set then the code is assumed to be 68K format. Without this flag being set, the°dONLNd7ˆ<Ï(Z"Component Manager will ignore any °dONLNdYıÏ)∞ComponentPlatformInfo°dONLNdnˆÉ)ì.°dONLNdp<π(8ZcomponentIconFamily°dONLNdÖ)<5y*
  381. Finally, the °dONLNdí(y4˛)=componentIconFamily°dONLNd•)˛5˛)Ö1 field allows you to provide the resource ID of a°dONLNd◊5<Aü(]ZRSystem 7 Icon Suite. If this field is 0, it indicates that there is no icon suite.°dONLNd*O<[[*count°dONLNd0h<t*0This is the number of elements contained in the °dONLNd`gs∞)·ComponentPlatformInfo°dONLNduh∞tœ)ì array.°dONLNd}Ç<éå(™Z
  382. platformArray°dONLNdãö<¶*/This is an array of elements that describe the °dONLNd∫ö¶˛)›/code to be used for different platforms. If the°dONLNdͶ<≤J(ŒZ1platform is for 68K, then the information within °dONLNd¶J≤˛(Œhthis element is a copy from the°dONLNd;≤<æû(€ZcomponentFlags°dONLNdI≥ûøø)b of the °dONLNdQ≤øæK)!ComponentDescription°dONLNde≥Køb)å and °dONLNdj≤bæ∂) ResourceSpec°dONLNdv≥∂ø˛)T of the original°dONLNdáø<À≥(ËZComponentResource°dONLNdò¿≥Ã)w structure. This °dONLNd©¿Ã˛)`*insures backwards compatibility with older°dONLNd‘Ã<ÿÍ(ÙZSComponent Managers. If the component contains native code support for the PowerPC, °dONLNd'ÃÍÿ˛(Ùthen°dONLNd,Ÿ<ÂØ(Zan element of the array °dONLNdDŸØÂk)s'will contain the information about its °dONLNdkÿk‰Õ)ºcomponentFlags°dONLNdyŸÕ²)b
  383. , resource°dONLNdÑÂ<Ò¶(
  384. Ztype, and resource ID.°dONLNdõ˛<
  385. Q*The °dONLNdü˝Q    •) platformType°dONLNd´˛•
  386. Ô)T field is a value °dONLNdΩ˛Ô
  387. ˛)J7that represents which platform the component code is to°dONLNdı <˚(3Z)support. The Gestalt result for selector °dONLNd
  388. ˚ï)øgestaltSysArchitecture°dONLNd4 ïÈ)ö will be matched °dONLNdE È˛)Twith°dONLNdJ<$x(@Z
  389. the value in °dONLNdWx#Ã)< platformType°dONLNdcÃ$)T of the °dONLNdk#g)$ComponentResource°dONLNd|g$‘)w. If a match is found, °dONLNdì‘$˛)m    then that°dONLNdù$<0(LZ+code is used to support the given platform.
  390.     °dONLNd >`Ií+$
  391. gestalt68k°dONLNd÷>ÃI‡)l= 1,°dONLNd›>8I›)l!/* Motorola MC68K architecture */°dONLNd    H`S¶(o~gestaltPowerPC°dONLNd    HÃS‡)l= 2,°dONLNd    H8SŒ)l/* IBM PowerPC architecture */°dONLNd    5`<k»(áZstruct ComponentPlatformInfo°dONLNd    Rj<uA*
  392. {°dONLNd    Ut`t+$
  393. long°dONLNd    \tÃ)lcomponentFlags;°dONLNd    lt8∞)l/* flags of Component */°dONLNd    Ü~`âú(•~ ResourceSpec°dONLNd    î~Ãâ˛)l
  394. component;°dONLNd    †~8â›)l!/* resource where Component code °dONLNd    »à8ì~*
  395.    is found */°dONLNd    ÿí`ùy(π~short°dONLNd    ‡íÃù
  396. )l
  397. platformType;°dONLNd    Ôí8ùÁ)l#/* gestaltSysArchitecture result */°dONLNd
  398. ú<ßF(√Z}; ’X’
  399. *(QT 05 - Component Manager 3.0(Ρ3) of 12(ZM.QT.Component Manager 3.0ˇL◊#ˇ ˇˇˇˇ#◊ 
  400. IR, Palatino
  401. .+6-Macintosh Technical Notes 040˘,Times
  402. °dONLNd /*$Component Manager version 3 routines
  403. °dONLNd%=I¢*GetComponentIconSuite,
  404. Courier°dONLNd;Wc´*GetComponentIconSuite°dONLNdPX´d5)ì returns an Icon Suite for the °dONLNdoX5d⁄)ä given component. This call works°dONLNdêdp1(å6only °dONLNdïd1p⁄)Uunder System 7 or later. If called on System 6, it returns an error. If the component°dONLNdÎp|É(ò6:doesn’t have an Icon Suite but does have a Component Icon °dONLNd%pÉ|⁄(ò°(as returned by°dONLNd5|àà(•6GetComponentInfo°dONLNdE}àâî)p), °dONLNdH|îà') GetComponentIconSuite°dONLNd]}'âì)ì creates an Icon Suite °dONLNdt}ìâ⁄)lcontaining just°dONLNdÑäñ(≤65the black-and-white Component Icon. In this way, you °dONLNdπäñG(≤=can use °dONLNd¡âGï⁄)(GetComponentIconSuite°dONLNd◊ñ¢Ù(æ6-whether or not a component has an Icon Suite.
  405.     °dONLNd∞ªè*Kpascal OSErr GetComponentIconSuite(Component aComponent, Handle *iconSuite)°dONLNdQƒœJ*
  406. aComponent°dONLNd\ƒ`œK)H/Component ID, retrieved with FindNextComponent.°dONLNd匟E(ı6    iconSuite°dONLNdñŒ`Ÿ7)H+Pointer to the Icon Suite you will receive.
  407. °dONLNd¬ÊÚá(6RegisterComponent°dONLNd‘Ú˛ª* RegisterComponentResource°dONLNdÓ˛
  408. —* RegisterComponentResourceFile°dONLNd $8*9The only change made to these routines was to modify the °dONLNdE8$⁄(@V use of the global parameter. The°dONLNdf$0≈(L6Vupper byte now contains the platform ID to be used by the component being registered. °dONLNdº$≈0⁄(L„This°dONLNd¡1=c(Y6Bchange is necessary because these calls do not have access to the °dONLNd0c<⁄(YÅComponentResource°dONLNd>Js(f6which contains the °dONLNd(=sI)[ComponentPlatformInfo°dONLNd=>JG)ì. If the upper °dONLNdL>GJ⁄)Abyte of the global parameter is°dONLNdlKWË(s6-zero, then the platform is assumed to be the °dONLNdôJËV5)– platform68k°dONLNd§K5W9)M.
  409. °dONLNd¶qÄM(ú6)How to create a PowerPC ComponentResource
  410. °dONLNd–éöê*MThe basics step for running on a Power Macintosh with a native component are:°dONLNd®¥>*:•  Create component code fragment with native PowerPC code°dONLNdY¥¿;* >•  Main entry point to code is a mixed mode routine descriptor°dONLNdò¿Ã* 0•  Package component code fragment as a resource°dONLNd…Ãÿ‘* _•  If you supply an interface for the component to be called directly, then for PowerPC code to°dONLNd-ÿ‰c* E   call your component you must provide custom glue to make the call.°dONLNdsÂÒÖ*
  411. •  Create the extended '°dONLNdã‰Ö°)mthng°dONLNdè°Ò)' resource using the °dONLNd§‰î)`ComponentPlatformInfo°dONLNd∫ˇ ('67Each of these steps are discussed in more detail below:°dONLNdÚ%Ú*$Creating the component code fragment°dONLNd3?õ*The first step in creating a °dONLNd43õ?⁄)É<native PowerPC component is to port your code.  For complete°dONLNdq?KÆ(g6details on porting to PowerPC, °dONLNdê?ÆK¡)ñsee °dONLNdî?¡K¢)*Inside Macintosh: PowerPC System Software.°dONLNdæ?¢K⁄)·   Especially°dONLNdÀKWÁ(s6*important for the following discussion is °dONLNdıKÁW⁄)œ+an understanding of the Mixed Mode and Code°dONLNd!Wcz(6Fragment Managers.°dONLNd4p| *1Like other code ported for PowerPC, anytime your °dONLNdep |°)Ùcode uses a callback function (°dONLNdÑo°{“)ïProcPtr°dONLNdãp“|⁄)1),°dONLNdé}âé(•6it must be converted to a °dONLNd®|éà˛)vUniversalProcPtr°dONLNd∏}˛â)p.  But °dONLNdø}â⁄)'unlike callbacks defined by the system,°dONLNdÁâï”(±6'callbacks to your component have their °dONLNd    â”ï⁄)ª4own function prototypes.  With the exception of some°dONLNd    Cï°}(Ω6Icallbacks defined for QuickTime components, there are no system supplied °dONLNd    åï}°⁄(Ωõfunction prototypes°dONLNd    †¢Æ%( 6or °dONLNd    £°%≠ú)
  412. UniversalProcPtrs°dONLNd    ¥¢úÆD)w$, so you must create these yourself. fi4fi˘
  413. (Û64) of 12(ÛqQT 05 - Component Manager 3.0+
  414. M.QT.ComponentManager3.0ˇ|◊#ˇ ˇˇˇˇ#◊ 
  415. IR, Palatino
  416. .+Z-Developer Technical Support(-˙
  417. March 1994 0X0,Times
  418. °dONLNd,<8[(TZIf, in °dONLNd,[8˛)Qresponse to a request code, your component dispatches to internal functions using,
  419. Courier°dONLNdY8<Dœ(aZCallComponentFunction°dONLNdn9œE·)ì or °dONLNdr8·D¡) CallComponentFunctionWithStorage°dONLNdí9¡Eˆ)‡ , then this °dONLNdû9ˆE˛)5is°dONLNd°F<R…(nZa place where you must use a °dONLNdæE…Q9)çUniversalProcPtr°dONLNdŒF9R=)p.°dONLNd–^<j†(ÜZHSuppose your component currently responds to an open request as follows:
  420.     °dONLNdx`É…+$switch (params->what)°dONLNd1Ç`çe*
  421. {°dONLNd4å`óˆ*
  422.     case kComponentOpenSelect:°dONLNdSåón)¥/* Open request */°dONLNdgñ`°y(Ω~    {°dONLNdo†Ñ´ÿ+$
  423. Dresult = CallComponentFunctionWithStorage (storage, params, MyOpen);°dONLNd∂™Ñµ¢*
  424. break;°dONLNdæ¥`øy(€~    }
  425. °dONLNdƒÃ<ÿ˘(ÙZ<MyOpen is an internal function callback, so you must create °dONLNdÃ˘ÿ˛(Ùa°dONLNdÿ<‰*(Z"RoutineDescriptor/UniversalProcPtr°dONLNd$Ÿ*ÂN)Ó
  426.  for it.  °dONLNd.ÿN‰x)$MyOpen°dONLNd4Ÿx‰)* is declared as follows:
  427.     °dONLNdMÛ<˛ü(ZGpascal ComponentResult MyOpen (Handle storage, ComponentInstance self);
  428. °dONLNdï <∫*The first step is to create a °dONLNd≥ ∫Ú)~ProcInfo°dONLNdª Ú`)8 value for this function:
  429.     °dONLNd’&<1Z(MZenum {°dONLNd‹0<;*
  430. (   uppMyOpenProcInfo = kPascalStackBased°dONLNd:`EU+$
  431. 1| RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))°dONLNd9D`Os*
  432. 7| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))°dONLNdrN`Y™*
  433. B| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(ComponentInstance)))°dONLNdµX<cF(Z};
  434. °dONLNd∏q<}*,Next you must update your source to build a °dONLNd‰p|ä)fiUniversalProcPtr°dONLNdÙqä}∑)p     and use °dONLNd˝q∑}˛)-it.  You could°dONLNd ~<äO(¶Zuse °dONLNd}Oâ€)NewRoutineDescriptor°dONLNd$~€ä˛)å> for this purpose, but the disadvantage is that creates a heap°dONLNdcä<ñE(≤Z5object which your component must dispose of properly.°dONLNdô£<Ø*-An alternate approach is to declare a global °dONLNdΔ¢Æ)ÃRoutineDescriptor°dONLNd◊£Ø¶)w     (global °dONLNd‡£¶Ø˛)'variables are not a°dONLNdÙØ<ªá(◊Z>problem for a native PowerPC component, since a code fragment °dONLNd2Øáª˛(◊•automatically has global°dONLNdKª<«m(„Z variables):
  435.     °dONLNdW’<‡}*
  436. #ifdef powerc°dONLNdefl<Í÷*
  437. RRoutineDescriptor MyOpenRD = BUILD_ROUTINE_DESCRIPTOR (uppMyOpenProcInfo, MyOpen);°dONLNd∏È<ÙZ*
  438. #endif
  439. °dONLNdø<
  440. ú*AIf you want your code to be compilable for both 68K and PowerPC, °dONLNdú
  441. ˛()∫using the Universal°dONLNd
  442. <ˆ(5Z_Interfaces, then to avoid a lot of conditional compilation, the following macros may be useful:
  443.     °dONLNdt'<2}*
  444. #ifdef powerc°dONLNdÇ1<<©*
  445. I#define CallComponentFunctionWithStorageUniv(storage, params, funcName) \°dONLNdÃ;<Fã*
  446. C   CallComponentFunctionWithStorage(storage, params, &funcName##RD)°dONLNdE<PE*
  447. 5#define CallComponentFunctionUniv(params, funcName) \°dONLNdFO<Z'*
  448. /   CallComponentFunction(params, &funcName##RD)°dONLNdvY<d€*
  449. S#define INSTANTIATE_ROUTINE_DESCRIPTOR(funcName) RoutineDescriptor funcName##RD = \°dONLNd c<nw*
  450. ?   BUILD_ROUTINE_DESCRIPTOR (upp##funcName##ProcInfo, funcName)°dONLNd
  451. m<xU*
  452. #else°dONLNdw<Ç©*
  453. I#define CallComponentFunctionWithStorageUniv(storage, params, funcName) \°dONLNdZÅ<å‡*
  454. T   CallComponentFunctionWithStorage(storage, params, (ComponentFunctionUPP)funcName)°dONLNdØã<ñE*
  455. 5#define CallComponentFunctionUniv(params, funcName) \°dONLNdÂï<†|*
  456. @   CallComponentFunction(params, (ComponentFunctionUPP)funcName)°dONLNd    &ü<™Z*
  457. #endif ’X’
  458. *%QT 05 - Component Manager 3.0(Ρ5) of 12(ZM.QT.Component Manager 3.0ˇt◊#ˇ ˇˇˇˇ#◊ 
  459. IR, Palatino
  460. .+6-Macintosh Technical Notes 040˘,Times
  461. °dONLNd!-Ñ*These macros, °dONLNd!Ñ- )lexactly analogous to ,
  462. Courier°dONLNd#  ,≥)úCallComponentFunction°dONLNd8!≥-⁄)ì and°dONLNd=-9¯(V6 CallComponentFunctionWithStorage°dONLNd].¯:ê)‡ , generate the appropriate code °dONLNd}.ê:⁄)ò
  463. when compiled°dONLNdã:F…(b6 for 68K and PowerPC.  Note that °dONLNd´:…F⁄)±1the PowerPC macro expansion depends on the global°dONLNd›FRè(o6RoutineDescriptor°dONLNdÓGèSŒ)w  name being °dONLNd˙FŒR)?
  464. FuncNameRD°dONLNdGS)F, °dONLNdGS⁄)%i.e. the name of the function with RD°dONLNd,T`p(|6appended.  The °dONLNd;Sp_B)XINSTANTIATE_ROUTINE_DESCRIPTOR°dONLNdYTB`≥)“ macro can be used °dONLNdlT≥`⁄)qfor that°dONLNdu`lA(à6purpose:
  465.     °dONLNd~zÖY*
  466. #ifdef powerc°dONLNdåÑè€*
  467. 'INSTANTIATE_ROUTINE_DESCRIPTOR(MyOpen);°dONLNd¥éô6*
  468. #endif
  469. °dONLNdªß≥≈*(This is identical to the declaration of °dONLNd„¶≈≤˝)≠MyOpenRD°dONLNdÎß˝≥ú)8% earlier, but simplifies the editing.°dONLNdøÀQ(Á6
  470. With all the °dONLNdøQÀ⁄)9Qconditional stuff out of the way, then the original code can simply be updated byN°dONLNdpÃÿî(Ù6
  471. replacing °dONLNdzÀî◊t)| CallComponentFunctionWithStorage°dONLNdöÃtÿ≈)‡ O°dONLNdõÃ≈ÿ⁄)Qwith°dONLNd†ÿ‰(6$CallComponentFunctionWithStorageUniv°dONLNdƒŸÂ)¸:
  472.     °dONLNd«Û<˛•(Zswitch (params->what)°dONLNdfi˝<A*
  473. {°dONLNd·<Õ*
  474.    case kComponentOpenSelect:°dONLNdn)ÿ/* Open request */°dONLNd<P(8Z   {°dONLNd`&æ+$
  475. Fresult = CallComponentFunctionWithStorageUniv(storage, params,MyOpen);°dONLNdd%`0~*
  476. break;°dONLNdl/<:P(VZ   }
  477. °dONLNdqGSh(o6FRepeat the above steps for all internal component dispatches you make.°dONLNd∏am∂*Setting the main entry point°dONLNd’{áŸ*(Lastly, you must set up the entry point °dONLNd˝{Ÿá⁄)¡1into your component correctly.  Unlike a 68K code°dONLNd/áìΔ(Ø6"resource, a PowerPC code fragment °dONLNdQáΔì⁄)Æ7(which your component will be) has a well defined entry°dONLNdâìü~(ª6Lpoint.  The Component Manager, rather than just jumping to the start of the °dONLNd’ì~ü⁄(ªúcode resource, will°dONLNdÈü´-(«6<call the main entry point, as defined when linking, instead.°dONLNd&∑√ß*IBut the Component Manager is 68K code, which means your main entry point °dONLNdo∑ß√⁄(fl≈    must be a°dONLNdy√œè(Ï6RoutineDescriptor°dONLNdäƒè–*)w".  You can set that up as follows:
  478.     °dONLNd≠fiÈ6(6pascal°dONLNd¥fi<Èá)$ComponentResult°dONLNdƒfi®Ⱥ)lmain°dONLNd…fiÃÈ0)$(ComponentParameters°dONLNdfifi8È`)l*params,°dONLNdÏËÃÛÔ(Í Handle°dONLNdÙËÛ_)H      storage);°dONLNdÚ˝Y(6
  479. #ifdef powerc°dONLNd¸6*
  480. enum {°dONLNd<Î+$
  481. #uppMainProcInfo = kPascalStackBased°dONLNdA`U+$
  482. 1| RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))°dONLNdv`%æ*
  483. F| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentParameters *)))°dONLNd¿$`/s*
  484. 7| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Handle)))°dONLNd¯.9"(U6};°dONLNd˚BMè*KRoutineDescriptor MainRD = BUILD_ROUTINE_DESCRIPTOR(uppMainProcInfo, main);°dONLNdGLW6*
  485. #endif
  486. °dONLNdNeq*3When you link the component, you must then specify °dONLNdÅdpB(ç6MainRD°dONLNdáeBqö)* as the entry point.°dONLNdúã7(ß6Note:°dONLNd¢<ãÇ)$>Your development environment may issue a warning because your °dONLNd‡Çã∂(߆
  487. main entry°dONLNdÎã<óù(≥ZLpoint is in a data section, not a code section.  You may ignore the warning. fi4fi˘
  488. (Û66) of 12(ÛqQT 05 - Component Manager 3.0+
  489. M.QT.ComponentManager3.0ˇö◊#ˇ ˇˇˇˇ#◊ 
  490. IR, Palatino
  491. .+Z-Developer Technical Support(-˙
  492. March 1994 0X0,Times
  493. °dONLNd <,[(HZNote:°dONLNd `,k)$If °dONLNd     k,⁄) Jyour code is dependent on C or C++ runtime initializations, then your main°dONLNdT-`9Õ(U~entry point would be ,
  494. Courier°dONLNdi,Õ8)m__start °dONLNdq,8s):or __cplusstart°dONLNdÄ-s9⁄)l, respectively, rather°dONLNdó9`E`(a~4than main.  Modify the previous example accordingly.°dONLNdÃS<_[({ZNote:°dONLNd—S[_¶)D Some components rely on a “fast dispatching” mechanism for calling °dONLNdS¶_⁄({ƒ    component°dONLNd_`k∑(á~functions.  This °dONLNd0_∑k⁄)W5mechanism is dependent on the 68K architecture and is°dONLNdfk`w∑(ì~unsupported for °dONLNdvk∑w⁄)W5native components, although it will work for emulated°dONLNd¨w`É;(ü~*components running on the Power Macintosh.°dONLNd◊ë<ù[(πZNote:°dONLNd‹ë[ùÃ)R In all these modifications for PowerPC, the most difficult thing to get right is °dONLNd.ëÃù⁄(πÍthe°dONLNd2ù`©ò(Δ~ProcInfo°dONLNd:ûò™1)8" value.  It’s very easy to make a °dONLNd\û1™⁄)ô$“cut and paste” error, or get a type°dONLNdÅ™`∂Ì(“~wrong (short instead of short °dONLNdü™Ì∂⁄)ç2*).  If your component is crashing the first thing°dONLNd“∑`√N(fl~2to check (and check and check and check!) are the °dONLNd∂N¬Ü)ÓProcInfo°dONLNd ∑Ü√´)8 values.°dONLNd—<›](˘Z/Packaging the PowerPC component into a resource°dONLNdEÎ<˜.*.PowerPC development tools create your PowerPC °dONLNdsÎ.˜˛)Ú+code in a code fragment in the data fork of°dONLNdü˜<£(ZLthe file.  Your component code must be a resource (the resource type and id °dONLNdΘ£˛(¡are specified in the°dONLNd<@(,Z'°dONLNd@\)thng°dONLNd\&)*' resource described below).  You can use °dONLNd/&˛) 'the MPW Rez “read” command to read from°dONLNdW<(8Z,the data fork into a resource.  For example:
  495.     °dONLNdÖ*`5
  496. +$"read 'mycp' (130) mycomponent.pef;
  497. °dONLNd®C<O\(kZreads °dONLNdÆC\O)  the code fragment from the file °dONLNdŒBNw)≤mycomponent.pef°dONLNd›CwO˛)i and creates the resource°dONLNd˜P<\@(xZ'°dONLNd¯O@[\)mycp°dONLNd¸P\\~)'(130).°dONLNdj<v(íZ'Providing an interface to the component°dONLNd,Ñ<ê‡*!If you wish your component to be °dONLNdMчê˛)§=called directly, you must also supply an interface so callers°dONLNdãê<ú(∏Z.know how to call it.  For standard functions, °dONLNdπêú˛)◊1such as Open, Close, Version, etc., this is not a°dONLNdÎú<®ô(ƒZCproblem as the Component Manager supplies functions to do this for °dONLNd.úô®˛(ƒ∑you.  Nor is this a°dONLNdB®<¥ª(–Zproblem if you are writing °dONLNd]®ª¥˛)?QuickTime components, as QuickTime supplies standard interfaces°dONLNdù¥<¿È(‹Z%and libraries for calling components.°dONLNd√Ã<ÿd*But one °dONLNdÀÃdÿ˛)(Rof the advantages of the Component Manager is it lets you define your own routines°dONLNdÿ<‰g(Z@with their own parameter lists, and for these routines you must °dONLNd^ÿg‰˛(Ö supply an interface.  Typically,°dONLNd‰<0( Z5for 68K this involved providing callers an interface °dONLNd¥‰0˛)Ù,file with function prototypes for your calls°dONLNd·<¸((Z2and inline 68K assembly to actually make the call.°dONLNd<y*AObviously, the inline 68K code is a problem for a native PowerPC °dONLNdUy˛(0ócaller, so you must provide°dONLNdq< »(<Zglue to accomplish the same °dONLNdç» ˛)å>thing.  The following discussion also applies to calling a 68K°dONLNdà<,é(HZDcomponent from PowerPC code.  The interface is the same, either way.°dONLNd    8<D≥*To take the example for °dONLNd    )8≥D‘)wInside °dONLNd    08‘Dâ)!!Macintosh: More Macintosh Toolbox°dONLNd    Q8âD˛)µ, page 6-30, you might°dONLNd    hD<PÑ(lZhave a call like:
  498.     °dONLNd    z^<i∏*Lpascal ComponentResult DrawerSetup (ComponentInstance myInstance, Rect *r) =°dONLNd    «h<s*
  499. -    ComponentCallNow (kDrawerSetUpSelect, 4);
  500. °dONLNd    ıÄ<å¨*ComponentCallNow°dONLNd
  501. Ũç,)p is a macro that expands °dONLNd
  502. Å,ç˛)Ä)to inline 68K code that pushes additional°dONLNd
  503. Hç<ôé(µZEparameters and then executes an A-trap to call the Component Manager. ’X’
  504. *6QT 05 - Component Manager 3.0(Ρ7) of 12(ZM.QT.Component Manager 3.0ˇfi◊#ˇ ˇˇˇˇ#◊ 
  505. IR, Palatino
  506. .+6-Macintosh Technical Notes 040˘,Times
  507. °dONLNdf*
  508. 9The first thing when using the new Universal Headers, is °dONLNd9f⁄(:Ñthat the definition of,
  509. Courier°dONLNdP*à(G6ComponentCallNow°dONLNd`à+∞)p> has changed slightly.  The above declaration would change to:
  510.     °dONLNdü9Dä(`6Jpascal ComponentResult DrawerSetup (ComponentInstance myInstance, Rect *r)°dONLNdÎCN˘*
  511. -    ComponentCallNow (kDrawerSetUpSelect, 4);
  512. °dONLNd[g*8The only difference in this declaration is that the ‘=’ °dONLNdQ[g⁄)˜+character is missing.  This is necessary to°dONLNd}gs(è63allow the code to compile for both 68K and PowerPC.°dONLNd±Äåj*For 68K code, °dONLNdøjã⁄)RComponentCallNow°dONLNdœÄ⁄åy)p continues to expand to inline °dONLNdÓÄyå⁄)ü68K code, but for°dONLNdçôb(µ6
  513. PowerPC, the °dONLNd
  514. åbò“)JComponentCallNow°dONLNdç“ô˘)p macro °dONLNd$ç˘ô⁄)')expands to nothing, which means the above°dONLNdNô•Å(¡6declaration reduces to:
  515.     °dONLNdf≥æî*Lpascal ComponentResult DrawerSetup (ComponentInstance myInstance, Rect *r) ;
  516. °dONLNd≥Ãÿ≤*You must now supply glue for °dONLNd–À≤◊ˇ)ö DrawerSetup°dONLNd€ÃˇÿÃ)M( that does the same thing on PowerPC as °dONLNdÃÃÿ⁄)Õthe°dONLNdÿ‰É(668K inlines would do.°dONLNd¸√*VThe strategy here is to mimic what 68K code calling your component would do.  Namely, °dONLNdu√¸⁄(·push°dONLNdz¸Ÿ($6)a bunch of parameters on the stack, then °dONLNd£¸Ÿ⁄)¡5call the component.  You do that by building a struct°dONLNdŸ©(06that looks like the parameters °dONLNd¯©å)ë%as they would appear on the 68K stack°dONLNdå≥)„.  Each °dONLNd%≥⁄)'    call will°dONLNd/ m(<6Krequire a different struct because each call can have different parameters.°dONLNd{-9ê*Use the struct below (°dONLNdë,ê8)xDrawerSetupGluePB°dONLNd¢-9h)w) as a template.  °dONLNd¥-h9⁄)aThe first three fields,°dONLNdÃ9Ez(b6componentFlags°dONLNd⁄:zFÉ)b, °dONLNd‹9ÉE)    componentParamSize°dONLNdÓ:F )~, and °dONLNdÙ9 E{)
  517. componentWhat°dONLNd:{F“)[ are required, as °dONLNd:“F⁄)Wis°dONLNdFRı(n60the last field, which is the component instance.°dONLNdG^jz*componentFlags°dONLNdU_zk
  518. )b is unused and should be zero.°dONLNdtwÉñ(†6componentParamSize°dONLNdÜxñѧ)~ is °dONLNdäx§Ñ⁄)Cthe size, in bytes, of the parameters to the call, not counting the°dONLNdŒÑêP(¨6
  519. component °dONLNdÿÑPê⁄)8Ninstance.  This is the same number that is passed as the second parameter in a°dONLNd'êúà(π6ComponentCallNow°dONLNd7ëàùI)p' macro call, and should be the same as °dONLNd^ëIù⁄)¡the size of the params struct,°dONLNd}ù©j(≈6discussed below.°dONLNd鵡s*
  520. componentWhat°dONLNdõ∂s¬„)[ is the selector for your °dONLNdµ∂„¬⁄)p4component call.  Its the same as the first parameter°dONLNdÍ√œ,(Î6to a °dONLNdÔ¬,Œú)ComponentCallNow°dONLNdˇ√úœ”)p  macro call.°dONLNd €Áë(6MThe params field is a separate struct that exactly mirrors your parameters.  °dONLNdY€ëÁ⁄(Ø
  521.  This must be°dONLNdgÁÛe(6customized for °dONLNdvÁeÛ⁄)MKyour call.  A separate struct is used here because it simplifies the sizeof°dONLNd¬Ùr(6calculation for the °dONLNd÷Ûrˇ)ZcomponentParamSize°dONLNdËÙZ)~ field.  Parameters in °dONLNdˇÙZ⁄)jthis struct are specified in°dONLNd :((6reverse°dONLNd#: «)" order from the parameter list.°dONLNdE&7(B6Note:°dONLNdK<&é)$Remember that °dONLNdYé&h)R(the struct mirrors 68K stack alignment, °dONLNdÅh&w)⁄not°dONLNdÑw&∂)  68K struct°dONLNdê&<2q(NZ alignment. °dONLNdõ&q2∂)5B This means that byte parameters, e.g. char or Boolean, get passed°dONLNdfi2<>¢(ZZMas two bytes, not one. The struct must mirror that fact, so you must declare °dONLNd    +2¢>∂(Z¿byte°dONLNd    0><J{(fZfields to be a °dONLNd    ?>{J∂)?Cbyte field followed by a pad byte field and take it into account in°dONLNd    ÉJ<V÷(rZ!your parameter size calculations.°dONLNd    ßdpv(å6Once you have the °dONLNd    πdvp⁄)^Istruct, initialize it as shown in the example, and call the component via°dONLNd
  522. p|è(ô6CallUniversalProc°dONLNd
  523. qè}ª)w
  524.  with the °dONLNd
  525. pª|+),CallComponentUPP°dONLNd
  526. .q+}5)p.  °dONLNd
  527. 1p5|•)
  528. CallComponentUPP°dONLNd
  529. Aq•}≥)p is °dONLNd
  530. Eq≥}⁄)declared°dONLNd
  531. N~äê(¶6for you and is part of the °dONLNd
  532. i}êâ‰)x InterfaceLib°dONLNd
  533. u~‰äÕ)T3.  You don't need to do anything special to use it.°dONLNd
  534. ©ñ¢¿(ø6uppCallComponentProcInfo°dONLNd
  535. ¡ó¿£≈)® °dONLNd
  536. ¬ó≈£⁄)7should have been in the interfaces, because the call is°dONLNd
  537. ˙£Ø
  538. (À65always the same, but it's not, so it's defined below. fi4fi˘
  539. *(8) of 12(ÛqQT 05 - Component Manager 3.0+
  540. M.QT.ComponentManager3.0ˇæ◊#ˇ ˇˇˇˇ#◊ 
  541. IR, Palatino
  542. .+Z-Developer Technical Support(-˙
  543. March 1994 0X0,
  544. Courier
  545.     °dONLNd<<GZ(cZenum {°dONLNdF<Q,*
  546. 0    uppCallComponentProcInfo = kPascalStackBased°dONLNd:PÑ[+H
  547. | RESULT_SIZE(kFourByteCode)°dONLNdYZÑe[*
  548. +| STACK_ROUTINE_PARAMETER(1, kFourByteCode)°dONLNdÖd<oF(ãZ};,Times
  549. °dONLNdàÜ<íA*#1Here’s the code for the glue function.  Once you °dONLNdπÜAí˛(Æ_%have the structure defined, create an°dONLNdflì<ü–(ªZ$instantiation of it, and initialize °dONLNdì–üá)î'it.  Finally, call the component using °dONLNd*íáû˛)∑CallUniversalProc°dONLNd<ü<´¥(«Zas shown in the example.
  550.     °dONLNdUµ<¿∏*Lpascal  ComponentResult  DrawerSetup (ComponentInstance myInstance, Rect *r)°dONLNd£ø< A*
  551. {°dONLNd•…<‘Õ*
  552. #define kDrawerSetupParamSize°dONLNd√…‘Å)¥ (sizeof (DrawerSetupParams))°dONLNd·›<Ë}(Z
  553. #ifdef powerc°dONLNdÔÁ<Ú»*
  554. #pragma options align=mac68k°dONLNd Ò<¸Z*
  555. #endif°dONLNd˚<Õ*
  556.    struct DrawerSetupParams {°dONLNd2`t+$
  557. Rect°dONLNd7ѱ)$    *theRect;°dONLNdC‹)ê(/* Your parameters go here!!  In reverse°dONLNdr¥*
  558.     order from parameter list. */°dONLNdì<$U(@Z   };°dONLNdô#<.J*
  559. 6   typedef struct DrawerSetupParams DrawerSetupParams;°dONLNd–7<BÕ*   struct DrawerSetupGluePB {°dONLNdÔA`L°+$
  560.  
  561. unsigned char°dONLNd˛AÃL)lcomponentFlags;°dONLNdA8Lµ)l/* Flags - set to zero */°dONLNd)K`V°(r~
  562. unsigned char°dONLNd8KÃV+)lcomponentParamSize;°dONLNdLK8V”)l/* Size of the params struct */°dONLNdmU``y(|~short°dONLNduUÃ`)lcomponentWhat;°dONLNdÑU8`Ï)l$/* The component request selector */°dONLNd™_`jµ(Ü~DrawerSetupParams°dONLNdº_ÃjÔ)lparams;°dONLNd≈_8j”)l/* The parameters, see above */°dONLNdÊi`tµ(ê~ComponentInstance°dONLNd¯iÃt˘)l    instance;°dONLNdi8t…)l/* This component instance */°dONLNd!s<~U(öZ   };°dONLNd'}<àJ*
  563. 6   typedef struct DrawerSetupGluePB DrawerSetupGluePB;°dONLNd^á<í}*
  564.  
  565. #ifdef powerc°dONLNdlë<ú√*
  566. #pragma options align=reset°dONLNdàõ<¶Z*
  567. #endif°dONLNdè•<∞    *
  568. )   DrawerSetupGluePB myDrawerSetupGluePB;°dONLNdππ<ƒ**   myDrawerSetupGluePB.componentFlags = 0;°dONLNd‰√<ŒÜ*
  569. B   myDrawerSetupGluePB.componentParamSize = kDrawerSetupParamSize;°dONLNd'Õ<ÿY*
  570. 9   yDrawerSetupGluePB.componentWhat = kDrawerSetUpSelect;°dONLNda◊<‚*
  571. *   myDrawerSetupGluePB.params.theRect = r;°dONLNdå·<Ï*
  572. -   myDrawerSetupGluePB.instance = myInstance;°dONLNd∫ı<*-   return CallUniversalProc(CallComponentUPP,°dONLNd͡Ñ
  573. y+H
  574. 1uppCallComponentProcInfo,  &myDrawerSetupGluePB);°dONLNd    <A(0Z}
  575. °dONLNd!<-û*IRepeat the above steps for all the public functions for your component.  °dONLNdg!û-˛(IºTo allow for future°dONLNd{-<92(UZ3updating, the best way to make this glue available °dONLNdÆ-29˛)ˆ+to your clients is to build the glue into a°dONLNd⁄9<E¯(aZ%Code Fragment Manager shared library °dONLNdˇ9¯E˛)º7that is built into your component.  Provide your client°dONLNd7E<Q(mZ*with an XCOFF file to link against.  That °dONLNdaEQ˛)Δ6way, if the glue changes, the client applications will°dONLNdòQ<]’(yZPnot have to be relinked.  Be sure you choose a unique name for the glue library °dONLNdËQ’]˛(yÛto avoid°dONLNdÒ]<iÆ(ÖZpossible name conflicts.°dONLNd
  576. w<ÉQ*-Creating the extended thng' ComponentResource ’X’
  577. *LQT 05 - Component Manager 3.0(Ρ9) of 12(ZM.QT.Component Manager 3.0ˇt◊#ˇ ˇˇˇˇ#◊ 
  578. IR, Palatino
  579. .+6-Macintosh Technical Notes 040˘,Times
  580. °dONLNdî*Here is how to create the ',
  581. Courier°dONLNdî∞)|thng°dONLNd∞∑)' °dONLNd!∑.)ComponentResource°dONLNd2.B)w for °dONLNd7B⁄)a component that supports both°dONLNdV+e(H6 platform68k°dONLNda e,~)M and °dONLNdf~+Á)platformPowerPC°dONLNdu Á,Ø)i'. This is the source for MPW Rez using °dONLNdú Ø,⁄)»
  582. the latest°dONLNdß-9ƒ(U6%version of Types.r that supports the °dONLNdÃ,ƒ8l)¨UseExtendedThingResource°dONLNd‰-l9¿)® template. Before °dONLNdˆ-¿9⁄)Tusing°dONLNd¸:FÅ(b6the new Types.r you °dONLNd:ÅFfl)ineed to define the °dONLNd#9flEá)^UseExtendedThingResource°dONLNd;:áF⁄)® conditional with°dONLNdMFRV(n6Cthe value 1. A  component defined with this resource will work for °dONLNdêFVR⁄(ntall previous versions of the°dONLNd≠S_2({67Component Manager. By keeping the original portions of °dONLNd‰S2_E({Pthe °dONLNdËRE^º)ComponentResource°dONLNd˘Sº_⁄)w setup°dONLNd`l:(à6for the °dONLNd_:ká)" platform68k°dONLNd`ál»)M information, °dONLNd!`»l⁄)A5it allows your component to work on all 68K Macintosh°dONLNdWlx(î61computers. Adding the new information about your °dONLNdàlx⁄)˝%code fragment for the Power Macintosh°dONLNdÆxÑq(†6Fallows the Component Manager for that machine to use your native code.
  583.     °dONLNdıíù¬*"resource 'thng' (128, purgeable) {°dONLNdúßw*
  584.     kComponentType,°dONLNd,¶±Ü*
  585.     kComponentSubType,°dONLNdC∞ªÜ*
  586.     kComponentCreator,°dONLNdZ∫≈§*
  587.     cmpWantsRegisterMessage,°dONLNdwƒœü*
  588.     kAnyComponentFlagsMask,°dONLNd쌟©*
  589.     k68KCodeType, k68KCodeID,°dONLNd±ÿ„«*
  590. #    'STR ', kComponentNameStringID,°dONLNd’‚Ì«*
  591. #    'STR ', kComponentInfoStringID,°dONLNd˘Ï˜©*
  592.     'ICON', kComponentIconID,°dONLNd §*#if UseExtendedThingResource°dONLNd4
  593. !*
  594. 5    0x00010001,                     /* version 1.1 */°dONLNdj¬*
  595. "    componentHasMultiplePlatforms,°dONLNdç)ü*
  596.     kComponentIconFamilyID,°dONLNd©(31*
  597.     {°dONLNdØ2={*
  598. G        cmpWantsRegisterMessage, k68KCodeType, k68KCodeID, platform68k,°dONLNd˜<G≤*
  599. R        cmpWantsRegisterMessage, kPowerPCCodeType, kPowerPCCodeID, platformPowerPC°dONLNdJFQ6*
  600.     };°dONLNdQP[6*
  601. #endif°dONLNdXZe"*
  602. };
  603. °dONLNd[r~8*If you °dONLNdbr8~⁄) Rhave a component that only supports the 68K Macintosh, then you do not need to use°dONLNdµãV(ß6
  604. the extended °dONLNd¬~VäÕ)>ComponentResource°dONLNd”Õãl)w! structure. However, if you wish °dONLNdÙlã⁄)üto utilize Icon Families°dONLNd
  605. åò’(¥6)and automatic version registration, then °dONLNd6å’ò))Ωuse the extended °dONLNdGã)ó†)TComponentResource°dONLNdXå†ò⁄)w  without the°dONLNdeò§´(¡6ComponentPlatformInfo°dONLNdzô´•Ø)ì °dONLNd{ôØ•)and do not set the °dONLNdéò§⁄)`componentHasMultiplePlatforms°dONLNd¨¶≤;(Œ6flag °dONLNd±¶;≤w)#of the °dONLNd∏•w±)<componentRegisterFlags°dONLNdŒ¶≤⁄)ö. You may also include the°dONLNdÈ≤æ´(€6ComponentPlatformInfo°dONLNd˛≥´øÆ)ì4 if you wish to and just have a single element that °dONLNd2≥Æø⁄(€à   describes°dONLNd<øÀö(Á6your 68K component code.°dONLNdU◊„ı*-If you have a “fat” component, with both 68K °dONLNdÇ◊ı„⁄)›,and PowerPC code, set the component flags as
  606. °dONLNdØ„Ôp( 63you would for the 68K only case and duplicate that  °dONLNd‚„pÔ⁄( éinformation in the°dONLNdıÔ˚´(6ComponentPlatformInfo°dONLNd
  607. ´¸à)ì) portion of the extended resource.  That °dONLNd3à¸⁄)›will allow your°dONLNdC¸7($6:component to work correctly for versions of the Component °dONLNd}¸7⁄($U!Manager that are not aware of the°dONLNdü    I(16
  608. extended '°dONLNd©Ie)1thng°dONLNd≠    eò) ' resource.°dONLNdπ!-8(I6If you °dONLNd¿!8-⁄) Qhave a component that only supports the PowerPC in native mode, then you must use°dONLNd    .:Z(V6
  609. the extended °dONLNd    -Z9—)BComponentResource°dONLNd    0.—:⁄)w. °dONLNd    2.⁄:⁄)    1In this case, some care must be taken so that the°dONLNd    d;G5(c6;component will not be registered on 68K machines.  Set the °dONLNd    ü:5Fâ(cS ResourceSpec°dONLNd    ´;âGå)T °dONLNd    ¨;åG÷)field in the non°dONLNd    º;÷G⁄)J-°dONLNd    ΩHT|(p6extended part of the '°dONLNd    ”G|Sò)dthng°dONLNd    ◊HòT ) ' resource °dONLNd    ‚H T÷)28to zero. In addition, set the component flags in the non°dONLNd
  610. H÷T⁄(pÙ-°dONLNd
  611. Uaπ(}6"extended part  of the resource to °dONLNd
  612. =Tπ`Z)°cmpWantsRegisterMessage°dONLNd
  613. TUZab)°, °dONLNd
  614. VUbañ) regardless °dONLNd
  615. aUña⁄)4
  616. of whether or°dONLNd
  617. oamƒ(â6$not you handle the register message.°dONLNd
  618. ìaƒm«)¨ °dONLNd
  619. îa«m⁄)5 This will cause the 68K Component Manager to attempt°dONLNd
  620.  my‡(ï6*to register your component, it will fail, °dONLNd
  621. Ùm‡y⁄)».because there is no 68K code resource and your°dONLNd #yÖ∂(°6!component will not be registered.°dONLNd Eíû£*For the PowerPC case, you °dONLNd _í£û)ãneed to include a single °dONLNd xëù±){ComponentPlatformInfo°dONLNd çí±û⁄)ì element°dONLNd ñû™…(Δ6#that describes your PowerPC native °dONLNd πû…™⁄)±2component code for PowerPC implementations of your fi4fi˘
  622. (Û610)
  623.  of 12(ÛqQT 05 - Component Manager 3.0+
  624. M.QT.ComponentManager3.0ˇN◊#ˇ ˇˇˇˇ#◊ 
  625. IR, Palatino
  626. .+Z-Developer Technical Support(-˙
  627. March 1994 0X0,Times
  628. °dONLNd <,®(HZMcomponent to be registered.  Set the component flags in the extended portion °dONLNdM ®,˛(HΔof the resource as°dONLNd`,<8†(TZyou would normally.
  629. °dONLNduR<a
  630. *)Component Manager interfaces,
  631. Courier
  632.     °dONLNdío<z¥*/* MPW Rez interfaces */°dONLNd´É<é‹* #define cmpWantsRegisterMessage °dONLNdÕÉéK)ÿ (1<<31)    °dONLNdŸÉ\é≈)H/* bits for component°dONLNd¯ç\òì*
  633.    flags */°dONLNd°<¨◊(»Z#define componentDoAutoVersion °dONLNd%°¨2)ÿ(1<<0)°dONLNd,°8¨L)$    °dONLNd1°\¨‘)$/* bits for registration°dONLNdQ´8∂í(“V          flags */°dONLNddµ<¿‹(‹Z #define componentWantsUnregister°dONLNdܵ¿2)ÿ(1<<1)°dONLNdçø< (ÊZ(#define componentAutoVersionIncludeFlags°dONLNd∂ø 2)ÿ(1<<2)°dONLNdΩ…<‘ı(Z%#define componentHasMultiplePlatforms°dONLNd„…‘2)ÿ(1<<3)°dONLNdÒ›<Ë}(Z
  634. type 'thng' {°dONLNdÁ`Ú∞+$
  635. literal longint;°dONLNdÁ\Úé)¸
  636. /* Type */°dONLNd!Ò`¸∞(~literal longint;°dONLNd6Ò\¸ù)¸
  637. /* Subtype */°dONLNdE˚`∞("~literal longint;°dONLNdZ˚\∂)¸/* Manufacturer */°dONLNdn`Œ(,~unsigned hex longint; °dONLNdà\≈)¸/* component flags */°dONLNdü`ƒ(6~unsigned hex longint°dONLNd¥ÃS)lkAnyComponentFlagsMask = 0;°dONLNd–\fi)ê/* component flags Mask */°dONLNdÏ`$∞(@~literal longint;°dONLNd\$ß)¸/* Code Type */°dONLNd#`.à(J~integer;°dONLNd #\.ù)¸
  638. /* Code ID */°dONLNd/-`8∞(T~literal longint;°dONLNdD-\8ß)¸/* Name Type */°dONLNdU7`Bà(^~integer;°dONLNdc7\Bù)¸
  639. /* Name ID */°dONLNdrA`L∞(h~literal longint;°dONLNdáA\Lß)¸/* Info Type */°dONLNdòK`Và(r~integer;°dONLNd¶K\Vù)¸
  640. /* Info ID */°dONLNdµU``∞(|~literal longint;°dONLNd U\`ß)¸/* Icon Type */°dONLNd€_`jà(Ü~integer;°dONLNdÈ_\jù)¸
  641. /* Icon ID */°dONLNd˜i<t»(êZ#if UseExtendedThingResource°dONLNds`~…+$
  642. unsigned hex longint;°dONLNd.s\~fi)¸/* version of Component */°dONLNdJ}`àà(§~longint;°dONLNdX}\àË)¸/* flags for registration */°dONLNdvá`íà(Æ~integer;°dONLNdÑá\íœ)¸/* resource id of Icon °dONLNd£ë\úò*
  643.    Family */°dONLNd±õ`¶7(¬~+longint = $$CountOf(ComponentPlatformInfo);°dONLNdfi•`∞
  644. *
  645. "wide array ComponentPlatformInfo {°dONLNdØ`∫‚*
  646.     unsigned hex longint; °dONLNd Ø\∫ )¸/* component  flags */°dONLNd8π`ƒƒ(‡~    literal longint;°dONLNdQπ\ƒß)¸/* Code Type */°dONLNdb√`Œú(Í~     integer;°dONLNdt√\Œù)¸
  647. /* Code ID */°dONLNdÉÕ`ÿU(Ù~1    integer platform68k = 1, platformPowerPC = 2;°dONLNdµÕ\ÿª)¸/* platform type */°dONLNd ◊`‚~(˛~    };°dONLNd—·<ÏZ(Z#endif°dONLNdÿÎ<ˆF*
  648. };°dONLNd€ˇ<
  649. ™*/* MPW C interfaces */°dONLNdÚ<Z*enum {°dONLNd˘<(»*
  650. #define gestaltComponentMgr °dONLNd()¥'cpnt'°dONLNd8(ø)H/* Component Mgr version */°dONLNd:1<<·(XZ!#define gestaltQuickTimeFeatures °dONLNd\1<)¥'qtrs'°dONLNdd18<∞)H/* QuickTime features */°dONLNd~;`F
  651. (b~"gestaltPPCQuickTimeLibPresent = 0,°dONLNd¢;8F›)ÿ!/* PowerPC QuickTime glue library°dONLNdÀE8Pà*
  652.    is present */°dONLNd‹c<nı(äZ%#define gestaltSysArchitecture 'sysa'°dONLNdc8nÿ)¸ /* Native System Architecture */°dONLNd%m`x´(î~gestalt68k = 1,°dONLNd8m8x›)ÿ!/* Motorola MC68K architecture */°dONLNd[w`Çø(û~gestaltPowerPC = 2,°dONLNdrw8ÇŒ)ÿ/* IBM PowerPC architecture */°dONLNdíã`ñ•(≤~A/* componentRegisterFlags flags for ComponentResourceExtension */°dONLNd’ï`†”*
  653. componentDoAutoVersion °dONLNdÓï†A)¥    = (1<<0),°dONLNd˘ü`™›(Δ~componentWantsUnregister °dONLNdü™A)¥    = (1<<1), ’X’
  654. (ÎZQT 05 - Component Manager 3.0(Î˙11)
  655.  of 12(ZM.QT.Component Manager 3.0ˇ
  656. ◊#ˇ ˇˇˇˇ#◊ 
  657. IR, Palatino
  658. .+6-Macintosh Technical Notes 040˘,
  659. Courier
  660.     °dONLNd<·+$ !componentAutoVersionIncludeFlags °dONLNd")¥    = (1<<2),°dONLNd-<'“(CZcomponentHasMultiplePlatforms °dONLNdL')¥= (1<<3)°dONLNdU&1"(M6};°dONLNdX:E§*struct ComponentPlatformInfo°dONLNduDO*
  661. {°dONLNdxN<YP+$
  662. long°dONLNdN®YÛ)lcomponentFlags;°dONLNdèNYå)l/* flags of Component */°dONLNd©X<c}(Z
  663. ResourceSpec °dONLNd∏X®c⁄)l
  664. component;°dONLNdƒXcπ)l!/* resource where Component code °dONLNdÏbmZ*
  665.    is found */°dONLNd¸l<wU(ìZshort°dONLNdl®wÈ)l
  666. platformType;°dONLNdlwë)l/* gestaltSysArchitecture°dONLNd5vÅP*
  667.    result */°dONLNdBÄã"(ß6};°dONLNdEäï?*
  668. ;typedef struct ComponentPlatformInfo ComponentPlatformInfo;°dONLNdÅû©©*struct ExtComponentResource {°dONLNd†®<≥†+$
  669. ComponentDescription°dONLNdµ®®≥∑)lcd;°dONLNdª®≥•)l/* Registration parameters */°dONLNd⁄≤<Ω}(ŸZ
  670. ResourceSpec °dONLNdË≤ÑΩ∂)H
  671. component;°dONLNdı≤Ωπ)ê!/* resource where Component code °dONLNdº«Z*
  672.    is found */°dONLNd-Δ<—x(ÌZ ResourceSpec°dONLNd:ΔÑ— )HcomponentName;°dONLNdJΔ—ñ)ê/* name string resource */°dONLNdf–<€x(˜Z ResourceSpec°dONLNds–Ñ€ )HcomponentInfo;°dONLNdÉ–€ñ)ê/* info string resource */°dONLNdü⁄<Âx(Z ResourceSpec°dONLNd¨⁄Ñ )HcomponentIcon;°dONLNdº⁄Âs)ê/* icon resource */°dONLNd—Ó<˘"(Z./* new data for Component Manager version 3 */°dONLNd¯<P*
  673. long°dONLNd¯ÑŸ)HcomponentVersion;°dONLNd¯ñ)ê/* version of Component */°dONLNd6<
  674. P()Zlong°dONLNd<Ñ
  675. ˜)HcomponentRegisterFlags;°dONLNdT
  676. †)ê/* flags for registration */°dONLNdr <U(3Zshort°dONLNdy ÑË)HcomponentIconFamily;°dONLNdè ¥)ê /* resource id of Icon Family */°dONLNd±<!P(=Zlong°dONLNd∑Ñ!¢)Hcount;°dONLNd¡!Ø)ê/* elements in platformArray */°dONLNd‚ <+ˇ(GZ'ComponentPlatformInfo platformArray[1];°dONLNd
  677. *5"(Q6};°dONLNd
  678. 4?5*
  679. 9typedef struct ExtComponentResource ExtComponentResource;,Times
  680. °dONLNdGZfÇ*'Further Reference: Ö4Ö˘°dONLNdZg*s.+
  681. •°dONLNd\g<s@)I°dONLNd]g@s )'nside Macintosh: More Macintosh Toolbox°dONLNdÑg sy)À (Component Manager)°dONLNdôs*.(õH•°dONLNdõs<%))Inside Macintosh: PowerPC System Software°dONLNdƒs%w)È
  682.  (Mixed Mode °dONLNd—sw⁄)RManager and Code°dONLNd‚<ãô(ßZFragment Manager)°dONLNdÙã*ó.(≥H•°dONLNdˆã<ó )LMacintosh Technical Note, Drawing Icons the System 7 Way (M.IM.IconDrawing). fi4fi˘
  683. (Û612)
  684.  of 12(ÛqQT 05 - Component Manager 3.0+
  685. M.QT.ComponentManager3.0ˇ